#include "field.h"
#include <iostream>
#include <fstream>
#include <windows.h>
#include <conio.h>

using namespace std;

field::field() : xsell(6),ysell(8),xportal(0),yportal(0)
/*konstruktor kelas field, tanpa parameter karena size dari field sudah default*/
{
	vector<int> Accessable_Dest;
	/*array of integer yang berisi kode dalam integer dari map-map yang bisa diakses melalui teleport dari shop*/
	Accessable_Dest.push_back(0);
	Accessable_Dest.push_back(2);
	//-----
	char cc;
	ifstream myfile;
	myfile.open("layout_field.in");
	if(myfile.is_open()) {
		for(int i=0;i<13;i++) {
			for(int j=0;j<13;j++) {
				myfile >> cc;
				if(cc=='#') {
					InsertObject(new Tanah(true,false),j,i);
				}else if(cc=='0') {
					InsertObject(new Tanah(true,false),j,i);
				}else if(cc=='1') {
					InsertObject(new Tanah(false,false),j,i);
				}else if(cc=='$'){
					InsertObject(new Tanah(true,true),j,i);
				}
			}
		}
	}
	myfile.close();
}

field::~field()
/*destruktor kelas field*/
{
	for(int i=0;i<13;i++) {
		for(int j=0;j<13;j++) {
			DeleteObject(j,i);
		}
	}
}

field::field(const field& other) : xsell(1),ysell(1),xportal(1),yportal(3)
/*copy konstruktor kelas field*/
{
	for(int i=0;i<13;i++) {
		for(int j=0;j<13;j++) {
			InsertObject(other.getObject(j,i),j,i);
		}
	}
}

//BELOM ADA PENANGANAN TIDAK ADA OBJECT
Object* field::getObject(int x,int y) const
/*Mengembalikan object pada koordinat x,y*/
{
	return (mfield[y][x]);	
}

bool field::IsSellingSpot(int x,int y)
/*Fungsi boolean, mengembalikkan apakah titik yang berkoordinat (x,y) merupakan selling point*/
{
	if ((x==xsell)&&(y==ysell))
	{
		return true;
	}
	else
	{
		return false;
	}
}

bool field::IsPlowable(int x, int y) 
/*Fungsi boolean, mengembalikan apakah titik yang berkoordinat (x,y) dapat dicangkul*/
{
	if(x>=0 && x<13 && y>=0 && y<13) {
		if (getObject(x,y)->getObjectType()==0)				//jika tanah
		{
			Tanah* t = dynamic_cast<Tanah*>(getObject(x,y));
			if(t)
			{											//jika casting berhasil
				if (t->isPlowed() || t->isNonPlantable() || t->isSellingSpot()) //jika sudah dibajak atau non plantable atau selling spot, return false
				{
					return false;
				}
				else	//jika belom dibajak
				{
					return true;
				}			
			}
		}
		else //jika bukan tanah
		{
			return false;
		}
	}else{
		return false;
	}
}

bool field::IsPlantable(int x, int y) 
/*Fungsi boolean, mengembalikan apakah titik yang berkoordinat (x,y) dapat ditanami*/
{
	if(x>=0 && x<13 && y>=0 && y<13) {
		if (getObject(x,y)->getObjectType()==0)				//jika tanah
		{
			Tanah* t = dynamic_cast<Tanah*>(getObject(x,y));
			if(t)
			{											//jika casting berhasil
				if (t->isNonPlantable()==false)//jika tanah tidak bisa ditanamai
				{
					return true;
				}
				else
				{
					return false;
				}
			}
		}
		else// jika bukan tanah
		{
			return false;
		}
	}else{
		return false;
	}
}

bool field::IsSlashable(int x, int y) 
/*Fungsi boolean, mengembalikan apakah titik yang berkoordinat (x,y) dapat disabit*/
{
	if(x>=0 && x<13 && y>=0 && y<13) {
		if (getObject(x,y)->getObjectType()==3)				//jika tanaman
		{
			return true;
		}
		else
		{
			return false;
		}
	}else{
		return false;
	}
}

bool field::IsWalkable(int x, int y) 
/*Fungsi boolean, mengembalikan apakah titik yang berkoordinat (x,y) dapat dilewati*/
{
	if(x>=0 && x<13 && y>=0 && y<13) {
		if(getObject(x,y)->getObjectType()==3)	//jika tanaman 
		{
			Plant* p = dynamic_cast<Plant*>(getObject(x,y));
			if(p->isSeed()) { //apakah masih bibit?
				return true;
			}else{
				return false;
			}
		}
		else // jika bukan kurcaci dan bukan tanaman
		{
			return true;
		}
	}else{
		return false;
	}
}

bool field::IsWaterable(int x, int y)
/*Fungsi boolean, mengembalikan apakah titik yang berkoordinat (x,y) dapat diairi*/
{
	if(x>=0 && x<13 && y>=0 && y<13) {
		if (getObject(x,y)->getObjectType()==3)				//jika tanaman
		{
			Plant* p = dynamic_cast<Plant*>(getObject(x,y));
			if(p) {
				return !p->isWatered(); //kalo belom disiram menghasilkan true
			}
		}
		else //jika bukan tanaman
		{
			return false;
		}
	}else{
		return false;
	}
}

bool field::IsHarvestable(int x, int y)
/*Fungsi boolean, mengembalikan apakah titik yang berkoordinat (x,y) dapat dipanen*/
{
	if(x>=0 && x<13 && y>=0 && y<13) {
		if (getObject(x,y)->getObjectType()!=3)//dia bukan tanaman
		{
			return false;
		}
		else
		{
			Plant* p = dynamic_cast<Plant*>(getObject(x,y));
			if(p)			
			{							//jika casting berhasil
				return p->isHarvest();
			}
		}
	}else{
		return false;
	}
}

void field::GrowAllPlant()
/*Prosedur yang menimbulkan efek menumbuhkan seluruh tanaman di ladang*/
{
	for(int i=0;i<13;i++) {
		for(int j=0;j<13;j++) {
			if(getObject(j,i)->getObjectType()==3) {//jika tanaman
				Plant* p = dynamic_cast<Plant*>(getObject(j,i));
				if(p) {
					p->grow();
				}
			}
		}
	}
}

void field::WaterAllPlant() 
/*Prosedur yang menimbulkan efek yang mengairi seluruh tanaman di ladang*/
{
	for(int i=0;i<13;i++) {
		for(int j=0;j<13;j++) {
			if(getObject(j,i)->getObjectType()==3) { //jika tanaman
				Plant* p = dynamic_cast<Plant*>(getObject(j,i));
				if(p) {
					p->watered();
				}
			}
		}
	}
}

void field::DieAllPlant() 
/*Prosedur yang menimbulkan efek mematikan seluruh tanaman yang ada di ladang*/
{
	for (int i=0;i<13;i++)
	{
		for (int j=0;j<13;j++)
		{
			if(getObject(j,i)->getObjectType()==3) {//jika dia adalah tanaman
				Plant* p = dynamic_cast<Plant*>(getObject(j,i));
				if(p)
				{		//jika casting berhasil
					p->SetUmur(0);
				}
			}
		}
	}
}

bool field::InsertPlant(Plant* obj, int x, int y)
/*Prosedur untuk memasukkan sebuah objek ke koordinat (x,y) secara keseluruhan*/
{	
	if(x>=0 && x<13 && y>=0 && y<13) {
		if (getObject(x,y)->getObjectType()==0)			//jika tanah
		{
			Tanah* t = dynamic_cast<Tanah*>(getObject(x,y));
			if(t)
			{											//jika casting berhasil
				if (!t->isNonPlantable() && t->isPlowed())//jika tanah bisa ditanam dan udah dibajak 
				{
					DeleteObject(x,y);
					InsertObject(obj,x,y);
					return true;
				}
				else
				{
					return false;
				}
			}
		}else{
			return false;
		}	
	}else{
		return false;
	}
}

void field::InsertObject(Object* obj,int x, int y) 
/*Prosedur untuk memasukkan sebuah objek ke koordinat (x,y)*/
{
	if(x>=0 && x<13 && y>=0 && y<13) {
		mfield[y][x] = obj;
	}else{
		cout << "Error: tidak bisa memasukkan object di kordinat tersebut" << endl;
	}
}

void field::DeleteObject(int x, int y) 
/*Prosedur untuk menghilangkan sebuah objek yang berada di koordinat (x,y)*/
{
	if(x>=0 && x<13 && y>=0 && y<13) {
		delete mfield[y][x];
	}else{
		cout << "Error: tidak bisa mendelete object di kordinat tersebut" << endl;
	}
}

vector<int> field::GetDestination() 
/*Fungsi getter untuk variable accesable_dest*/
{
	vector<int> a;
	a.push_back(0);
	return a; 
}

//kurang tumbuhan lainnya
void field::Display(int xplayer,int yplayer, int player_direction,int xkurcharvest,int ykurcharvest,int kurcharvest_direction, int xkurcwater, int ykurcwater,int kurcwater_direction, int xkurcslash, int ykurcslash,int kurcslash_direction)
/*Fungsi untuk menampilkan interface ladang kepada player.*/
{
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
		
	int xiterasi = 0;
	int yiterasi = 0;
	char playerkiri = (char) 17;
	char playerkanan = (char) 16;
	char playeratas = (char) 30;
	char playerbawah = (char) 31;
	char kurcharvestkiri = (char) 27;
	char kurcharvestkanan = (char) 26;
	char kurcharvestatas = (char) 24;
	char kurcharvestbawah = (char) 25;
	char kurcslashkiri = (char)  180;
	char kurcslashkanan = (char) 195;
	char kurcslashatas = (char) 193;
	char kurcslashbawah = (char) 194;
	
	//system ("cls");
        gotoxy(0,0);
        //for(int i = 1; i <= 16; i++)
        //    cout<< "               \n";
        gotoxy(0,0);
	for(int i=0;i<=14;i++) {
		SetConsoleTextAttribute (hOut, BPI);
		cout << "_";
		SetConsoleTextAttribute (hOut, FW);
	}
	cout << endl;
	for(int i=0;i<13;i++) {
		SetConsoleTextAttribute (hOut, BPI);
		cout << "|";
		SetConsoleTextAttribute (hOut, FW);
		for(int j=0;j<13;j++) {
			if(i==yplayer  && j==xplayer) {
				if(player_direction==0) {
					SetConsoleTextAttribute (hOut, FRI);
					cout << playerkiri;
					SetConsoleTextAttribute (hOut, FW);
				}else if(player_direction==1) {
					SetConsoleTextAttribute (hOut, FRI);
					cout << playerkanan;
					SetConsoleTextAttribute (hOut, FW);
				}else if(player_direction==2) {
					SetConsoleTextAttribute (hOut, FRI);
					cout << playeratas;
					SetConsoleTextAttribute (hOut, FW);
				}else if(player_direction==3) {
					SetConsoleTextAttribute (hOut, FRI);
					cout << playerbawah;
					SetConsoleTextAttribute (hOut, FW);
				}
			}else if(i==ykurcharvest && j==xkurcharvest) {
				if(kurcharvest_direction==0) {
					SetConsoleTextAttribute (hOut, FGI);
					cout << kurcharvestkiri;
					SetConsoleTextAttribute (hOut, FW);
				}else if(kurcharvest_direction==1) {
					SetConsoleTextAttribute (hOut, FGI);
					cout << kurcharvestkanan;
					SetConsoleTextAttribute (hOut, FW);
				}else if(kurcharvest_direction==2) {
					SetConsoleTextAttribute (hOut, FGI);
					cout << kurcharvestatas;
					SetConsoleTextAttribute (hOut, FW);
				}else if(kurcharvest_direction==3) {
					SetConsoleTextAttribute (hOut, FGI);
					cout << kurcharvestbawah;
					SetConsoleTextAttribute (hOut, FW);
				}
			}else if(i==ykurcwater && j==xkurcwater) {
				if(kurcwater_direction==0) {
					SetConsoleTextAttribute (hOut, FBI);
					cout << "<";
					SetConsoleTextAttribute (hOut, FW);
				}else if(kurcwater_direction==1) {
					SetConsoleTextAttribute (hOut, FBI);
					cout << ">";
					SetConsoleTextAttribute (hOut, FW);
				}else if(kurcwater_direction==2) {
					SetConsoleTextAttribute (hOut, FBI);
					cout << "^";
					SetConsoleTextAttribute (hOut, FW);
				}else if(kurcwater_direction==3) {
					SetConsoleTextAttribute (hOut, FBI);
					cout << "V";
					SetConsoleTextAttribute (hOut, FW);
				}
			}else if(i==ykurcslash && j==xkurcslash) {
				if(kurcslash_direction==0) {
					SetConsoleTextAttribute (hOut, FP);
					cout << kurcslashkiri;
					SetConsoleTextAttribute (hOut, FW);
				}else if(kurcslash_direction==1) {
					SetConsoleTextAttribute (hOut, FP);
					cout << kurcslashkanan;
					SetConsoleTextAttribute (hOut, FW);
				}else if(kurcslash_direction==2) {
					SetConsoleTextAttribute (hOut, FP);
					cout << kurcslashatas;
					SetConsoleTextAttribute (hOut, FW);
				}else if(kurcslash_direction==3) {
					SetConsoleTextAttribute (hOut, FP);
					cout << kurcslashbawah;
					SetConsoleTextAttribute (hOut, FW);
				}
			}else{
				if(getObject(j,i)->getObjectType()==3) {
					Plant* p;
					p=dynamic_cast<Plant*>(getObject(j,i));
					if(p) {
						if(p->isMati()) {
							SetConsoleTextAttribute (hOut, FR);
							cout << "x";
							SetConsoleTextAttribute (hOut, FW);
						}else if(p->isWatered()) {
							SetConsoleTextAttribute (hOut, BBI);
							if(p->isSeed()) {
								cout << ".";
							}else{
								if(p->GetPlantId()==0) {
									cout << "c";
								}else if(p->GetPlantId()==1) {
									cout << "m";
								}else if(p->GetPlantId()==2) {
									cout << "w";
								}else if(p->GetPlantId()==3) {
									cout << "j";
								}else if(p->GetPlantId()==4) {
									cout << "M";
								}else if(p->GetPlantId()==5) {
									cout << "p";
								}else if(p->GetPlantId()==6) {
									cout << "J";
								}
							}
							SetConsoleTextAttribute (hOut, FW);
						}else if(p->isSeed()) {
							SetConsoleTextAttribute (hOut, BG);
							cout << ".";
							SetConsoleTextAttribute (hOut, FW);
						}else if(p->GetPlantId()==0) {
							SetConsoleTextAttribute (hOut, BG);
							cout << "c";
							SetConsoleTextAttribute (hOut, FW);
						}else if(p->GetPlantId()==1) {
							SetConsoleTextAttribute (hOut, BG);
							cout << "m";
							SetConsoleTextAttribute (hOut, FW);
						}else if(p->GetPlantId()==2) {
							SetConsoleTextAttribute (hOut, BG);
							cout << "w";
							SetConsoleTextAttribute (hOut, FW);
						}else if(p->GetPlantId()==3) {
							SetConsoleTextAttribute (hOut, BG);
							cout << "j";
							SetConsoleTextAttribute (hOut, FW);
						}else if(p->GetPlantId()==4) {
							SetConsoleTextAttribute (hOut, BG);
							cout << "M";
							SetConsoleTextAttribute (hOut, FW);
						}else if(p->GetPlantId()==5) {
							SetConsoleTextAttribute (hOut, BG);
							cout << "p";
							SetConsoleTextAttribute (hOut, FW);
						}else if(p->GetPlantId()==6) {
							SetConsoleTextAttribute (hOut, FW);
							cout << "J";
							SetConsoleTextAttribute (hOut, FW);
						}
					}
				}else if(getObject(j,i)->getObjectType()==0){
					Tanah* t;
					t = dynamic_cast<Tanah*>(getObject(j,i));
					if(t) {
						if(t->isSellingSpot()){
							SetConsoleTextAttribute (hOut, BGI);
							cout << "$";
							SetConsoleTextAttribute (hOut, FW);
						}else if(t->isNonPlantable()) {
							SetConsoleTextAttribute (hOut, BW);
							cout << "*";
							SetConsoleTextAttribute (hOut, FW);
						}else if(t->isPlowed()){
							SetConsoleTextAttribute (hOut, FP);
							cout << "#";
							SetConsoleTextAttribute (hOut, FW);
						}else {
							SetConsoleTextAttribute (hOut, BY);
							cout << " ";
							SetConsoleTextAttribute (hOut, FW);
						}
					}
				}
			}
			xiterasi++;
			//cout << xiterasi << " " << yiterasi << endl;
		}
		SetConsoleTextAttribute (hOut, BPI);
		cout << "|";
		SetConsoleTextAttribute (hOut, FW);
		cout << endl;
		yiterasi++;
	}
	for(int i=0;i<=14;i++) {
		SetConsoleTextAttribute (hOut, BPI);
		cout << "_";
		SetConsoleTextAttribute (hOut, FW);
	}
	cout << endl;
	cout << endl;
        gotoxy(0,17); cout<< "\t\t\t\t\t\t\t\t";
        gotoxy(0,17); cout<< ">";
}
